package com.booking.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.booking.common.dto.PageReq;
import com.booking.common.dto.PageResp;
import com.booking.common.enums.BookingErrorCode;
import com.booking.common.exception.BookingException;
import com.booking.common.utils.ConvertUtils;
import com.booking.common.utils.DtUtils;
import com.booking.common.utils.LocalDateTimeUtils;
import com.booking.controller.model.req.order.OrderPageQueryReq;
import com.booking.controller.model.req.order.RoomOrderCancelReq;
import com.booking.controller.model.req.order.RoomOrderCommentReq;
import com.booking.controller.model.req.order.RoomOrderCreateReq;
import com.booking.controller.model.req.order.ServiceOrderCancelReq;
import com.booking.controller.model.req.order.ServiceOrderCommentReq;
import com.booking.controller.model.req.order.ServiceOrderCreateReq;
import com.booking.controller.model.res.RoomOrderDetail;
import com.booking.controller.model.res.ServiceOrderDetail;
import com.booking.dao.entity.AuditRecord;
import com.booking.dao.entity.HomestayInfo;
import com.booking.dao.entity.RoomCommentDetail;
import com.booking.dao.entity.RoomInfo;
import com.booking.dao.entity.RoomOrder;
import com.booking.dao.entity.ServiceCommentDetail;
import com.booking.dao.entity.ServiceInfo;
import com.booking.dao.entity.ServiceOrder;
import com.booking.dao.entity.UserInfo;
import com.booking.dao.service.AuditRecordService;
import com.booking.dao.service.HomestayInfoService;
import com.booking.dao.service.RoomCommentDetailService;
import com.booking.dao.service.RoomInfoService;
import com.booking.dao.service.RoomOrderService;
import com.booking.dao.service.ServiceCommentDetailService;
import com.booking.dao.service.ServiceInfoService;
import com.booking.dao.service.ServiceOrderService;
import com.booking.dao.service.UserInfoService;
import com.booking.enums.AuditStatusEnums;
import com.booking.enums.OrderCommentStatusEnums;
import com.booking.enums.OrderPayStatusEnums;
import com.booking.enums.OrderStatusEnums;
import com.booking.enums.RoomCheckStatusEnums;
import com.booking.enums.UserTypeEnum;
import com.booking.service.OrderService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author Qikai.Lin
 * @date 2023/4/23
 */
@Slf4j
@Service
public class OrderServiceImpl implements OrderService {


    @Autowired
    private HomestayInfoService homestayInfoService;
    @Autowired
    private RoomInfoService roomInfoService;
    @Autowired
    private ServiceInfoService serviceInfoService;
    @Autowired
    private UserInfoService userInfoService;
    @Autowired
    private RoomOrderService roomOrderService;
    @Autowired
    private ServiceOrderService serviceOrderService;
    @Autowired
    private AuditRecordService auditRecordService;
    @Autowired
    private RoomCommentDetailService roomCommentDetailService;
    @Autowired
    private ServiceCommentDetailService serviceCommentDetailService;

    private RoomOrder getRoomOrder(Long orderId) {
        RoomOrder roomOrder = roomOrderService.getById(orderId);
        if (roomOrder == null) {
            throw new BookingException(BookingErrorCode.ORDER_NOT_EXIST);
        }
        return roomOrder;
    }

    private ServiceOrder getServiceOrder(Long orderId) {
        ServiceOrder serviceOrder = serviceOrderService.getById(orderId);
        if (serviceOrder == null) {
            throw new BookingException(BookingErrorCode.ORDER_NOT_EXIST);
        }
        return serviceOrder;
    }

    private UserInfo getUserInfo(Long userId) {
        UserInfo userInfo = userInfoService.getById(userId);
        if (userInfo == null) {
            throw new BookingException(BookingErrorCode.USER_NOT_EXIST);
        }
        return userInfo;
    }

    private RoomInfo getRoomInfo(Long roomId) {
        RoomInfo roomInfo = roomInfoService.getById(roomId);
        if (roomInfo == null) {
            throw new BookingException(BookingErrorCode.ROOM_NOT_EXIST);
        }
        return roomInfo;
    }


    // 将RoomOrder转化为RoomOrderDetail
    private RoomOrderDetail transToRoomOrderDetail(RoomOrder roomOrder) {
        RoomOrderDetail orderDetail = ConvertUtils.convert(RoomOrderDetail.class, roomOrder);
        // 填充订单信息
        orderDetail.setOrderId(roomOrder.getId());
        // 转化日期
        orderDetail.setBookingDate(LocalDateTimeUtils.toYyyyMMddStr(roomOrder.getBookingDate()));
        orderDetail.setCheckInDate(LocalDateTimeUtils.toYyyyMMddStr(roomOrder.getCheckInDate()));
        orderDetail.setCheckOutDate(LocalDateTimeUtils.toYyyyMMddStr(roomOrder.getCheckOutDate()));

        // 转化状态
        orderDetail.setOrderStatus(OrderStatusEnums.getMsgByStatus(roomOrder.getOrderStatus()));
        orderDetail.setPayStatus(OrderPayStatusEnums.getMsgByStatus(roomOrder.getPayStatus()));
        orderDetail.setCheckStatus(RoomCheckStatusEnums.getMsgByStatus(roomOrder.getCheckStatus()));
        orderDetail.setCommentStatus(OrderCommentStatusEnums.getMsgByStatus(roomOrder.getCommentStatus()));

        // 填充民宿房间信息
        RoomInfo roomInfo = roomInfoService.getById(roomOrder.getRoomId());
        ConvertUtils.copy(orderDetail, roomInfo);
        orderDetail.setRoomName(roomInfo.getName());

        HomestayInfo homestayInfo = homestayInfoService.getById(roomInfo.getHomestayId());
        orderDetail.setOwnerId(homestayInfo.getOwnerId());
        orderDetail.setHomestayName(homestayInfo.getName());

        return orderDetail;
    }

    // 将ServiceOrder转化为ServiceOrderDetail
    private ServiceOrderDetail transToServiceOrderDetail(ServiceOrder serviceOrder) {
        ServiceOrderDetail orderDetail = ConvertUtils.convert(ServiceOrderDetail.class, serviceOrder);
        // 填充订单信息
        orderDetail.setOrderId(serviceOrder.getId());
        // 转化日期
        orderDetail.setBookingDate(LocalDateTimeUtils.toYyyyMMddStr(serviceOrder.getBookingDate()));
        orderDetail.setServiceDate(LocalDateTimeUtils.toYyyyMMddStr(serviceOrder.getServiceDate()));

        // 转化状态
        orderDetail.setOrderStatus(OrderStatusEnums.getMsgByStatus(serviceOrder.getOrderStatus()));
        orderDetail.setPayStatus(OrderPayStatusEnums.getMsgByStatus(serviceOrder.getPayStatus()));
        orderDetail.setCommentStatus(OrderCommentStatusEnums.getMsgByStatus(serviceOrder.getCommentStatus()));

        // 填充民宿服务信息
        ServiceInfo serviceInfo = serviceInfoService.getById(serviceOrder.getServiceId());
        ConvertUtils.copy(orderDetail, serviceInfo);
        orderDetail.setServiceName(serviceInfo.getName());

        HomestayInfo homestayInfo = homestayInfoService.getById(serviceOrder.getHomestayId());
        orderDetail.setOwnerId(homestayInfo.getOwnerId());
        orderDetail.setHomestayName(homestayInfo.getName());

        return orderDetail;
    }

    @Override
    public PageResp<RoomOrderDetail> getRoomOrderPage(PageReq<OrderPageQueryReq> request) {
        log.info("分页查询房间订单");
        PageResp<RoomOrder> page = roomOrderService.page(request);
        List<RoomOrder> roomOrders = page.getRecords();
        List<RoomOrderDetail> roomOrderDetails = new ArrayList<>();
        roomOrders.forEach(order -> {
            roomOrderDetails.add(transToRoomOrderDetail(order));
        });

        PageResp<RoomOrderDetail> resPage = new PageResp<>();
        resPage.setCurrent(page.getCurrent());
        resPage.setHasNext(page.isHasNext());
        resPage.setSize(page.getSize());
        resPage.setTotal(page.getTotal());
        resPage.setRecords(roomOrderDetails);
        return resPage;
    }


    @Override
    public RoomOrderDetail getRoomOrderDetail(Long orderId) {
        log.info("房间订单详情查询 orderId={}", orderId);
        RoomOrder roomOrder = getRoomOrder(orderId);

        RoomOrderDetail orderDetail = transToRoomOrderDetail(roomOrder);

        log.info("房间订单详情查询成功！ orderDetail={}", JSON.toJSONString(orderDetail));
        return orderDetail;
    }

    @Override
    public RoomOrder createRoomOrder(RoomOrderCreateReq request) {
        log.info("创建房间订单 request={}", JSON.toJSONString(request));
        // 查询房间信息
        RoomInfo roomInfo = getRoomInfo(request.getRoomId());

        // 校验预订时间是否合法
        // 查询订单信息
        List<RoomOrder> roomOrders = roomOrderService.getListByRoomId(request.getRoomId());
        // 过滤掉END状态的订单
        List<RoomOrder> bookingOrders = roomOrders.stream()
                .filter(order -> !Objects.equals(order.getOrderStatus(), OrderStatusEnums.END.getStatus()))
                .collect(Collectors.toList());
        Set<String> bookingDtSet = new HashSet<>();
        bookingOrders.forEach(order -> {
            List<String> dtRange = DtUtils.getDtRange(order.getCheckInDate(), order.getCheckOutDate());
            bookingDtSet.addAll(dtRange);
        });
        // 校验预订时间是否已在预订时间列表中
        if (bookingDtSet.contains(request.getCheckInDate()) || bookingDtSet.contains(request.getCheckOutDate())) {
            throw new BookingException(BookingErrorCode.ROOM_ALREADY_BOOKING);
        }

        // 订单落库
        RoomOrder roomOrder = new RoomOrder();
        roomOrder.setId(IdWorker.getId());
        roomOrder.setRoomId(request.getRoomId());
        roomOrder.setVisitorId(request.getUserId());
        roomOrder.setHomestayId(roomInfo.getHomestayId());

        LocalDateTime checkInDate = LocalDateTimeUtils.yyyyMMddStrToLocalDateTime(request.getCheckInDate());
        LocalDateTime checkOutDate = LocalDateTimeUtils.yyyyMMddStrToLocalDateTime(request.getCheckOutDate());
        long days = LocalDateTimeUtils.getDurationDays(checkInDate, checkOutDate);

        roomOrder.setCheckInDate(checkInDate);
        roomOrder.setCheckOutDate(checkOutDate);
        roomOrder.setBookingDays((int)days);

        roomOrder.setOrderStatus(OrderStatusEnums.INIT.getStatus());
        roomOrder.setPayStatus(OrderPayStatusEnums.NOT_PAY.getStatus());
        roomOrder.setCommentStatus(OrderCommentStatusEnums.NOT_COMMENT.getStatus());
        roomOrder.setCheckStatus(RoomCheckStatusEnums.NOT_CHECK.getStatus());

        roomOrder.setBookingDate(LocalDateTimeUtils.timestampToLocalDateTime(System.currentTimeMillis()));

        BigDecimal bookingPrices = roomInfo.getBookingPrices().multiply(BigDecimal.valueOf(days));
        BigDecimal totalPrices = roomInfo.getPrices().multiply(BigDecimal.valueOf(days));
        //TODO 优惠价格根据用户会员等级定义
        BigDecimal discountPrices = BigDecimal.ZERO;

        roomOrder.setBookingPrices(bookingPrices);
        roomOrder.setTotalPrices(totalPrices);
        roomOrder.setDiscountPrices(discountPrices);
        roomOrder.setPayPrices(totalPrices.subtract(discountPrices));
        roomOrderService.save(roomOrder);
        log.info("房间订单创建成功！ roomOrder={}", JSON.toJSONString(roomOrder));
        return roomOrder;
    }

    @Override
    public void cancelRoomOrder(RoomOrderCancelReq request) {
        log.info("房间订单取消 request={}", JSON.toJSONString(request));
        Long roomOrderId = request.getRoomOrderId();
        Long userId = request.getUserId();
        // 查询订单
        RoomOrder roomOrder = getRoomOrder(request.getRoomOrderId());
        // 判断是否已完成
        if (Objects.equals(OrderStatusEnums.END.getStatus(), roomOrder.getOrderStatus()) &&
            Objects.equals(OrderPayStatusEnums.RETURNED.getStatus(), roomOrder.getPayStatus())) {
            throw new BookingException(BookingErrorCode.ORDER_ALREADY_END);
        }
        // 修改订单状态为审核中
        roomOrder.setOrderStatus(OrderStatusEnums.AUDITING.getStatus());
        roomOrderService.updateById(roomOrder);
        // 查询用户
        UserInfo userInfo = getUserInfo(request.getUserId());
        // 订单取消记录落库
        AuditRecord auditRecord = new AuditRecord();
        auditRecord.setId(IdWorker.getId());
        auditRecord.setRoomOrderId(roomOrderId);
        if (Objects.equals(UserTypeEnum.VISITOR.getType(), userInfo.getUserType())) {
            auditRecord.setVisitorId(userId);
        } else if (Objects.equals(UserTypeEnum.HOMESTAY_OWNER.getType(), userInfo.getUserType())) {
            auditRecord.setOwnerId(userId);
        }
        auditRecord.setCancelOrderReason(request.getCancelReason());
        auditRecord.setAuditStatus(AuditStatusEnums.READY_EXAMINE.getStatus());
        auditRecordService.save(auditRecord);
        log.info("取消申请已存档，等待管理员审核！");
        // 等待管理员审核、取消
    }

    @Override
    public void shutdownRoomOrder(Long orderId) {
        log.info("房间订单终止 orderId={}", orderId);
        // 查询订单
        RoomOrder roomOrder = getRoomOrder(orderId);
        roomOrder.setPayStatus(OrderPayStatusEnums.RETURNED.getStatus());
        roomOrder.setOrderStatus(OrderStatusEnums.END.getStatus());
        roomOrderService.updateById(roomOrder);
        log.info("订单终止成功！");
    }

    @Override
    public void commentRoomOrder(RoomOrderCommentReq request) {
        log.info("房间订单评价 request={}", JSON.toJSONString(request));
        Long roomOrderId = request.getRoomOrderId();
        Long userId = request.getUserId();
        // 查询订单
        RoomOrder roomOrder = getRoomOrder(request.getRoomOrderId());
        // 是否已评价过
        if (Objects.equals(roomOrder.getCommentStatus(), OrderCommentStatusEnums.COMMENTED.getStatus())) {
            throw new BookingException(BookingErrorCode.ORDER_ALREADY_COMMENTED);
        }
        // 是否是此订单用户
        if (!Objects.equals(request.getUserId(), roomOrder.getVisitorId())) {
            throw new BookingException(BookingErrorCode.ORDER_NOT_FOR_THIS_USER);
        }
        // 是否订单已完成
        if (!Objects.equals(OrderStatusEnums.END.getStatus(), roomOrder.getOrderStatus())) {
            throw new BookingException(BookingErrorCode.ORDER_NOT_END);
        }
        // 评论落库
        RoomCommentDetail commentDetail = new RoomCommentDetail();
        commentDetail.setRoomOrderId(roomOrderId);
        commentDetail.setHomestayId(roomOrder.getHomestayId());
        commentDetail.setUserId(userId);
        commentDetail.setContent(request.getContent());
        commentDetail.setScore(request.getScore());
        roomCommentDetailService.save(commentDetail);

        // 更新订单的评论状态
        roomOrder.setCommentStatus(OrderCommentStatusEnums.COMMENTED.getStatus());
        roomOrderService.updateById(roomOrder);
        log.info("评论成功！");
    }

    @Override
    public void checkRoomOrder(Long orderId) {
        log.info("房间订单入住 orderId={}", orderId);
        RoomOrder roomOrder = getRoomOrder(orderId);

        // 是否到入住日期
        if (roomOrder.getCheckInDate().isAfter(LocalDateTime.now())) {
            throw new BookingException(BookingErrorCode.NOT_IN_BOOKING_TIME);
        }
        // 是否已入住
        if (Objects.equals(RoomCheckStatusEnums.CHECKED.getStatus(), roomOrder.getCheckStatus())) {
            throw new BookingException(BookingErrorCode.ALREADY_CHECKED);
        }
        // 是否已支付
        if (!Objects.equals(OrderPayStatusEnums.PAYED.getStatus(), roomOrder.getPayStatus())) {
            throw new BookingException(BookingErrorCode.ORDER_NOT_PAYED);
        }
        roomOrder.setOrderStatus(OrderStatusEnums.START.getStatus());
        roomOrder.setCheckStatus(RoomCheckStatusEnums.CHECKED.getStatus());
        roomOrderService.updateById(roomOrder);
        log.info("房间入住成功！");
    }

    @Override
    public void finishRoomOrder(Long orderId) {
        log.info("房间订单完成 orderId={}", orderId);
        RoomOrder roomOrder = getRoomOrder(orderId);
        // 是否已入住
        if (!Objects.equals(RoomCheckStatusEnums.CHECKED.getStatus(), roomOrder.getCheckStatus())) {
            throw new BookingException(BookingErrorCode.ORDER_NOT_CHECK);
        }
        // 更新房间订单入住状态
        roomOrder.setOrderStatus(OrderStatusEnums.END.getStatus());
        roomOrderService.updateById(roomOrder);
        log.info("订单完成！");
    }

    @Override
    public void payRoomOrderBooking(Long orderId) {
        log.info("房间订单支付定金 orderId={}", orderId);
        RoomOrder roomOrder = getRoomOrder(orderId);
        // 是否支付定金
        if (Objects.equals(OrderPayStatusEnums.BOOKING_PAYED.getStatus(), roomOrder.getPayStatus())) {
            throw new BookingException(BookingErrorCode.BOOKING_PAYED);
        }
        // 更新房间订单定金支付状态
        roomOrder.setOrderStatus(OrderStatusEnums.BOOKING.getStatus());
        roomOrder.setPayStatus(OrderPayStatusEnums.BOOKING_PAYED.getStatus());
        roomOrderService.updateById(roomOrder);
        log.info("支付成功！");
    }

    @Override
    public void payRoomOrder(Long orderId) {
        log.info("房间订单支付全款 orderId={}", orderId);
        RoomOrder roomOrder = getRoomOrder(orderId);
        // 是否已支付
        if (Objects.equals(OrderPayStatusEnums.PAYED.getStatus(), roomOrder.getPayStatus())) {
            throw new BookingException(BookingErrorCode.ORDER_ALREADY_PAYED);
        }
        // 更新房间订单支付状态
        roomOrder.setOrderStatus(OrderStatusEnums.BOOKING.getStatus());
        roomOrder.setPayStatus(OrderPayStatusEnums.PAYED.getStatus());
        roomOrderService.updateById(roomOrder);
        log.info("支付成功！");
    }


    @Override
    public PageResp<ServiceOrderDetail> getServiceOrderPage(PageReq<OrderPageQueryReq> request) {
        log.info("分页查询服务订单");
        PageResp<ServiceOrder> page = serviceOrderService.page(request);
        List<ServiceOrder> serviceOrders = page.getRecords();
        List<ServiceOrderDetail> serviceOrderDetails = new ArrayList<>();
        serviceOrders.forEach(order -> {
            serviceOrderDetails.add(transToServiceOrderDetail(order));
        });

        PageResp<ServiceOrderDetail> resPage = new PageResp<>();
        resPage.setCurrent(page.getCurrent());
        resPage.setHasNext(page.isHasNext());
        resPage.setSize(page.getSize());
        resPage.setTotal(page.getTotal());
        resPage.setRecords(serviceOrderDetails);
        return resPage;
    }




    @Override
    public ServiceOrderDetail getServiceOrderDetail(Long orderId) {
        log.info("服务订单详情查询 orderId={}", orderId);
        ServiceOrder serviceOrder = getServiceOrder(orderId);

        ServiceOrderDetail orderDetail = transToServiceOrderDetail(serviceOrder);

        log.info("服务订单详情查询成功！ orderDetail={}", JSON.toJSONString(orderDetail));
        return orderDetail;
    }

    @Override
    public ServiceOrder createServiceOrder(ServiceOrderCreateReq request) {
        log.info("创建服务订单 request={}", JSON.toJSONString(request));
        // 查询房间信息
        ServiceInfo serviceInfo = getServiceInfo(request.getServiceId());

        // 校验预订时间是否合法
        // 查询订单信息
        List<ServiceOrder> serviceOrders = serviceOrderService.getListByServiceId(request.getServiceId());
        // 过滤掉END状态的订单
        List<ServiceOrder> bookingOrders = serviceOrders.stream()
                .filter(order -> !Objects.equals(order.getOrderStatus(), OrderStatusEnums.END.getStatus()))
                .collect(Collectors.toList());
        Set<String> bookingDtSet = new HashSet<>();
        bookingOrders.forEach(order -> {
            bookingDtSet.add(DtUtils.getDtStr(order.getServiceDate()));
        });
        // 校验预订时间是否已在预订时间列表中
        if (bookingDtSet.contains(request.getServiceDate())) {
            throw new BookingException(BookingErrorCode.SERVICE_ALREADY_BOOKING);
        }

        // 订单落库
        ServiceOrder serviceOrder = new ServiceOrder();
        serviceOrder.setId(IdWorker.getId());
        serviceOrder.setServiceId(request.getServiceId());
        serviceOrder.setVisitorId(request.getUserId());
        serviceOrder.setHomestayId(serviceInfo.getHomestayId());

        serviceOrder.setServiceDate(LocalDateTimeUtils.yyyyMMddStrToLocalDateTime(request.getServiceDate()));

        serviceOrder.setOrderStatus(OrderStatusEnums.INIT.getStatus());
        serviceOrder.setPayStatus(OrderPayStatusEnums.NOT_PAY.getStatus());
        serviceOrder.setCommentStatus(OrderCommentStatusEnums.NOT_COMMENT.getStatus());

        serviceOrder.setBookingDate(LocalDateTimeUtils.timestampToLocalDateTime(System.currentTimeMillis()));

        //TODO 优惠价格根据用户会员等级定义
        BigDecimal discountPrices = BigDecimal.ZERO;

        serviceOrder.setBookingPrices(serviceInfo.getBookingPrices());
        serviceOrder.setTotalPrices(serviceInfo.getPrices());
        serviceOrder.setDiscountPrices(discountPrices);
        serviceOrder.setPayPrices(serviceInfo.getPrices().subtract(discountPrices));
        serviceOrderService.save(serviceOrder);
        log.info("服务订单创建成功！ serviceOrder={}", JSON.toJSONString(serviceOrder));
        return serviceOrder;
    }

    @Override
    public void cancelServiceOrder(ServiceOrderCancelReq request) {
        log.info("服务订单取消 request={}", JSON.toJSONString(request));
        Long serviceOrderId = request.getServiceOrderId();
        Long userId = request.getUserId();
        // 查询订单
        ServiceOrder serviceOrder = getServiceOrder(serviceOrderId);
        if (Objects.equals(OrderStatusEnums.END.getStatus(), serviceOrder.getOrderStatus()) &&
            Objects.equals(OrderPayStatusEnums.RETURNED.getStatus(), serviceOrder.getPayStatus())) {
            throw new BookingException(BookingErrorCode.ORDER_ALREADY_END);
        }
        // 修改订单状态为审核中
        serviceOrder.setOrderStatus(OrderStatusEnums.AUDITING.getStatus());
        serviceOrderService.updateById(serviceOrder);
        // 查询用户
        UserInfo userInfo = getUserInfo(request.getUserId());
        // 订单取消记录落库
        AuditRecord auditRecord = new AuditRecord();
        auditRecord.setServiceOrderId(serviceOrderId);
        if (Objects.equals(UserTypeEnum.VISITOR.getType(), userInfo.getUserType())) {
            auditRecord.setVisitorId(userId);
        } else if (Objects.equals(UserTypeEnum.HOMESTAY_OWNER.getType(), userInfo.getUserType())) {
            auditRecord.setOwnerId(userId);
        }
        auditRecord.setCancelOrderReason(request.getCancelReason());
        auditRecord.setAuditStatus(AuditStatusEnums.READY_EXAMINE.getStatus());
        auditRecordService.save(auditRecord);
        log.info("取消申请已存档，等待管理员审核！");
        // 等待管理员审核、取消
    }

    @Override
    public void shutdownServiceOrder(Long orderId) {
        log.info("服务订单终止 orderId={}", orderId);
        // 查询订单
        ServiceOrder serviceOrder = getServiceOrder(orderId);
        serviceOrder.setPayStatus(OrderPayStatusEnums.RETURNED.getStatus());
        serviceOrder.setOrderStatus(OrderStatusEnums.END.getStatus());
        serviceOrderService.updateById(serviceOrder);
        log.info("订单终止成功！");
    }


    @Override
    public void commentServiceOrder(ServiceOrderCommentReq request) {
        log.info("服务订单评价 request={}", JSON.toJSONString(request));
        Long serviceOrderId = request.getServiceOrderId();
        Long userId = request.getUserId();
        // 查询订单
        ServiceOrder order = getServiceOrder(serviceOrderId);
        // 是否已评价过
        if (Objects.equals(order.getCommentStatus(), OrderCommentStatusEnums.COMMENTED.getStatus())) {
            throw new BookingException(BookingErrorCode.ORDER_ALREADY_COMMENTED);
        }
        // 是否是此订单用户
        if (!Objects.equals(request.getUserId(), order.getVisitorId())) {
            throw new BookingException(BookingErrorCode.ORDER_NOT_FOR_THIS_USER);
        }
        // 是否订单已完成
        if (!Objects.equals(OrderStatusEnums.END.getStatus(), order.getOrderStatus())) {
            throw new BookingException(BookingErrorCode.ORDER_NOT_END);
        }
        // 评论落库
        ServiceCommentDetail commentDetail = new ServiceCommentDetail();
        commentDetail.setServiceOrderId(serviceOrderId);
        commentDetail.setHomestayId(order.getHomestayId());
        commentDetail.setUserId(userId);
        commentDetail.setContent(request.getContent());
        commentDetail.setScore(request.getScore());
        serviceCommentDetailService.save(commentDetail);

        // 更新订单的评论状态
        order.setCommentStatus(OrderCommentStatusEnums.COMMENTED.getStatus());
        serviceOrderService.updateById(order);
        log.info("评论成功！");
    }

    @Override
    public void payServiceOrderBooking(Long orderId) {
        log.info("服务订单支付定金 orderId={}", orderId);
        // 查询订单
        ServiceOrder serviceOrder = getServiceOrder(orderId);
        // 是否支付定金
        if (Objects.equals(OrderPayStatusEnums.BOOKING_PAYED.getStatus(), serviceOrder.getPayStatus())) {
            throw new BookingException(BookingErrorCode.BOOKING_PAYED);
        }
        // 更新房间订单定金支付状态
        serviceOrder.setOrderStatus(OrderStatusEnums.BOOKING.getStatus());
        serviceOrder.setPayStatus(OrderPayStatusEnums.BOOKING_PAYED.getStatus());
        serviceOrderService.updateById(serviceOrder);
        log.info("支付成功！");
    }

    @Override
    public void payServiceOrder(Long orderId) {
        log.info("服务订单支付全款 orderId={}", orderId);
        // 查询订单
        ServiceOrder serviceOrder = getServiceOrder(orderId);
        // 是否已支付
        if (Objects.equals(OrderPayStatusEnums.PAYED.getStatus(), serviceOrder.getPayStatus())) {
            throw new BookingException(BookingErrorCode.ORDER_ALREADY_PAYED);
        }
        // 更新房间订单支付状态
        serviceOrder.setPayStatus(OrderPayStatusEnums.PAYED.getStatus());
        serviceOrderService.updateById(serviceOrder);
        log.info("支付成功！");
    }

    @Override
    public void finishServiceOrder(Long orderId) {
        log.info("服务订单确认履约 orderId={}", orderId);
        // 查询订单
        ServiceOrder serviceOrder = getServiceOrder(orderId);
        // 更新房间订单状态
        serviceOrder.setOrderStatus(OrderStatusEnums.END.getStatus());
        serviceOrderService.updateById(serviceOrder);
        log.info("履约成功！");
    }

    private ServiceInfo getServiceInfo(Long serviceId) {
        ServiceInfo serviceInfo = serviceInfoService.getById(serviceId);
        if (serviceInfo == null) {
            log.error("创建服务订单失败：民宿服务不存在 serviceId={}", serviceId);
            throw new BookingException(BookingErrorCode.SERVICE_NOT_EXIST);
        }
        return serviceInfo;
    }




}
